package com.cloudinnov.logic.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.cloudinnov.dao.BoardSolutionConfigDao;
import com.cloudinnov.dao.ControlSolutionDao;
import com.cloudinnov.dao.ScheduleJobDao;
import com.cloudinnov.dao.TriggerDao;
import com.cloudinnov.dao.mongo.EquipmentControlLogMongoDBDao;
import com.cloudinnov.logic.BxManagerLogic;
import com.cloudinnov.logic.EquipmentControlLogic;
import com.cloudinnov.logic.JobTaskLogic;
import com.cloudinnov.logic.TriggerLogic;
import com.cloudinnov.model.BoardSolutionConfig;
import com.cloudinnov.model.ControlSolution;
import com.cloudinnov.model.Trigger;
import com.cloudinnov.task.model.ScheduleJob;
import com.cloudinnov.utils.CodeUtil;
import com.cloudinnov.utils.CommonUtils;
import com.cloudinnov.utils.JudgeNullUtil;
import com.cloudinnov.utils.RemoteControllerUtil;
import com.cloudinnov.utils.control.ControlModel;
import com.cloudinnov.utils.control.EquipmentControlLog;

@Service("tiggerLogic")
public class TriggerLogicImpl extends BaseLogicImpl<Trigger> implements TriggerLogic {
    public final Logger log = LoggerFactory.getLogger(this.getClass());
    private static final int TIGGER_RULE_TIME = 1;
    @SuppressWarnings("unused")
    private static final int TIGGER_RULE_CONDITION = 2;
    @SuppressWarnings("unused")
    private static final int REPEAT_PERIOD_DAY = 1;
    private static final int REPEAT_PERIOD_WEEK = 2;
    private static final int REPEAT_PERIOD_MONTH = 3;
    private static final int REPEAT_PERIOD_YEAR = 4;
    private static final int SOLUTION_TYPE_INFO_BOARD = 1;
    @SuppressWarnings("unused")
    private static final int SOLUTION_TYPE_INFO_OTHER = 2;
    private int digit = 5;
    @Autowired
    private TriggerDao tiggerDao;
    @Autowired
    private JobTaskLogic jobTaskLogic;
    @Autowired
    private ControlSolutionDao controlSolutionDao;
    @Autowired
    private BoardSolutionConfigDao boardSolutionConfigDao;
    @Autowired
    private ScheduleJobDao scheduleJobDao;
    @Autowired
    private BxManagerLogic bxManagerLogic;
    @Autowired
    private EquipmentControlLogic equipmentControlLogic;
    @Autowired
    private EquipmentControlLogMongoDBDao equipmentControlLogMongoDBDao;

    /**
     * 触发器添加
     */
    public int save(Trigger tigger) {
        String tiggerCode = CodeUtil.tiggerCode(digit);// 生成触发器code
        tigger.setCode(tiggerCode);
        tigger.setStatus(CommonUtils.STATUS_NORMAL);
        int result = tiggerDao.insert(tigger);
        if (result == CommonUtils.SUCCESS_NUM) {
            if (tigger.getTiggerRule() != null && tigger.getTiggerRule() == TIGGER_RULE_TIME) {
                ScheduleJob job = new ScheduleJob();
                job.setJobGroup(ScheduleJob.JOB_TIGGER);
                job.setObjectCode(tiggerCode);
                job.setJobStatus("1");
                job.setBeanClass(JobTaskLogicImpl.TIGGER_CLASS_PATH);
                job.setMethodName(JobTaskLogicImpl.TIGGER_CLASS_METHOD);
                job.setDescription(CommonUtils.ENV);
                job.setEffectTime(tigger.getEffectTime());
                job.setExpireTime(tigger.getExpireTime());
                job.setEnv(CommonUtils.ENV);
                job.setRun(0);
                String[] crons = getCron(tigger);
                String jobInfo = "";
                String jobInfos = "";
                int isExist = 0;
                for (String str : crons) {
                    List<ScheduleJob> JobList = scheduleJobDao.selectListByJobGroup(job.getJobGroup());
                    job.setJobName(ScheduleJob.JOB_NAME_TIGGER + System.currentTimeMillis());
                    job.setJobGroup(ScheduleJob.JOB_GROUP_TIGGER);
                    job.setCronExpression(str);
                    if (JobList != null && JobList.size() > 0) {
                        for (ScheduleJob item : JobList) {
                            jobInfo = item.getJobGroup() + "-" + item.getCronExpression() + "-" + item.getEnv();
                            jobInfos = job.getJobGroup() + "-" + job.getCronExpression() + "-" + job.getEnv();
                            if (jobInfos.equals(jobInfo)) {
                                isExist = 0;
                                break;
                            } else {
                                isExist = 1;
                            }
                        }
                    } else {
                        isExist = 1;
                    }
                    if (isExist == 1) {
                        isExist = jobTaskLogic.addTask(job);// 任务添加到数据库
                        jobTaskLogic.addJob(job);// 任务添加到quartz内存中
                    }
                }
            }
            return CommonUtils.SUCCESS_NUM;
        } else {
            return CommonUtils.DEFAULT_NUM;
        }
    }
    @Override
    public int delete(Trigger model) {
        // TODO Auto-generated method stub
        ScheduleJob jobModel = new ScheduleJob();
        jobModel.setObjectCode(model.getCode());
        jobModel = scheduleJobDao.selectEntityByCondition(jobModel);
        if (jobModel != null) {// 停止正在运行的quartz任务并且更改数据库状态
            jobTaskLogic.changeStatus(jobModel.getJobId(), JobTaskLogicImpl.JOB_STOP_CMD);
        }
        return tiggerDao.deleteByCondition(model);
    }
    /***
     * convert Date to cron ,eg. "0 06 10 15 1 ? 2014"
     * @param date : 时间点
     * @return
     */
    public static String[] getCron(Trigger tigger) {
        String[] times = tigger.getTimeRule().split("\\" + CommonUtils.SPLIT_VERTICAL_LINE);
        String[] crons = new String[times.length];
        String cron = "* ";
        String week = "*";
        Calendar rightNow = Calendar.getInstance();// 将时间戳转化成cron
        if (times != null) {
            for (int i = 0; i < times.length; i++) {
                rightNow.setTimeInMillis(Long.parseLong(times[i]));
                if (tigger.getRepeatPeriod() == 1) {
                    cron = "0 " + rightNow.get(Calendar.MINUTE) + " " + rightNow.get(Calendar.HOUR_OF_DAY) + " * * ?";
                } else {
                    cron = "0 " + rightNow.get(Calendar.MINUTE) + " " + rightNow.get(Calendar.HOUR_OF_DAY) + " ";
                }
                crons[i] = cron;
            }
        }
        if (tigger.getRepeatPeriod() == REPEAT_PERIOD_WEEK) {// 周
            String[] weeks = tigger.getWeek().replaceAll("星期", "").split("\\|");
            for (int i = 0; i < weeks.length; i++) {
                if (i == 0) {
                    week = String.valueOf(CommonUtils.chineseNumber2Int(weeks[i]));
                    continue;
                }
                week += "," + CommonUtils.chineseNumber2Int(weeks[i]);
            }
            for (int i = 0; i < crons.length; i++) {
                crons[i] = crons[i] + "? * " + week;
            }
        } else if (tigger.getRepeatPeriod() == REPEAT_PERIOD_MONTH) {// 月
            for (int i = 0; i < crons.length; i++) {
                crons[i] = crons[i] + tigger.getMonthDay().replaceAll("\\|", ",") + " * ?";
            }
        } else if (tigger.getRepeatPeriod() == REPEAT_PERIOD_YEAR) {// 年
            String[] yearTime = tigger.getYearDay().split("\\|");
            String[] years = new String[yearTime.length * crons.length];
            int j = 0;
            for (String value : yearTime) {
                rightNow.setTimeInMillis(Long.parseLong(value));
                for (int i = 0; i < crons.length; i++) {
                    int month = rightNow.get(Calendar.MONTH) + 1;// 获取当前月份需加1
                    years[j] = crons[i] + rightNow.get(Calendar.DATE) + " " + month + " ? *";
                    j++;
                }
            }
            return years;
        }
        return crons;
    }
    @Override
    public int controlBoardSolutionByTiggercode(String tiggerCode, ScheduleJob jobDetail) {
        int returnCode = 0;
        // 根据触发器编码查询群控方案
        List<ControlSolution> list = controlSolutionDao.selectListByTriggerCode(tiggerCode);
        if (list != null && list.size() > 0) {
            BoardSolutionConfig model = null;// 设备控制配置
            for (ControlSolution controlSolution : list) {
                // 判断群控方案是否是情报板
                if (controlSolution != null && controlSolution.getSolutionType() == SOLUTION_TYPE_INFO_BOARD) {
                    model = new BoardSolutionConfig();
                    model.setSolutionCode(controlSolution.getCode());
                    List<BoardSolutionConfig> configs = boardSolutionConfigDao.selectListBySolutionCode(model);// 查询群控方案下的所有配置列表
                    if (JudgeNullUtil.iList(configs)) {
                        for (BoardSolutionConfig config : configs) {
                            if (config.getEquipmentCode() != null) {
                                bxManagerLogic.sendTextsToBoardUserForSolution(config.getEquipmentCode(), configs);
                            }
                        }
                    }
                }
            }
        }
        return returnCode;
    }
    @Override
    public int controlBoardSolutionByFaultcode(String faultCode) {
        int returnCode = 0;
        List<Trigger> list = tiggerDao.selectListByFaultCode(faultCode);// 根据故障码查询触发器
        List<ControlSolution> controlSolutionList = null;// 群控方案
        for (Trigger triggers : list) {
            controlSolutionList = controlSolutionDao.selectListByTriggerCode(triggers.getCode());
            BoardSolutionConfig model = null;// 设备控制配置
            for (ControlSolution controlSolution : controlSolutionList) {
                // 判断群控方案是否是情报板
                if (controlSolution != null && controlSolution.getSolutionType() == SOLUTION_TYPE_INFO_BOARD) {
                    model = new BoardSolutionConfig();
                    model.setSolutionCode(controlSolution.getCode());
                    List<BoardSolutionConfig> configs = boardSolutionConfigDao.selectListBySolutionCode(model);// 查询群控方案下的所有配置列表
                    if (JudgeNullUtil.iList(configs)) {
                        for (BoardSolutionConfig config : configs) {
                            if (config.getEquipmentCode() != null) {
                                bxManagerLogic.sendTextsToBoardUserForSolution(config.getEquipmentCode(), configs);
                            }
                        }
                    }
                }
            }
        }
        return returnCode;
    }
    @Override
    public int updateOnOff(Trigger trigger) {
        if (trigger.getCode() != null) {
            tiggerDao.updateOnOff(trigger);
            return 1;
        } else {
            return 0;
        }
    }
    @Override
    public int triggerControllerEquipments(Trigger tigger) {
        int result = 0;
        // 根据触发器查询群控方案
        List<ControlSolution> controlSolutions = controlSolutionDao.selectControllerSolution(tigger.getCode());
        List<List<ControlModel>> list = new ArrayList<List<ControlModel>>();
        if (JudgeNullUtil.iList(controlSolutions)) {
            for (ControlSolution controlSolution : controlSolutions) {
                List<ControlModel> data = equipmentControlLogic.generateControllerCommond(controlSolution);// 生成控制命令
                if (JudgeNullUtil.iList(data)) {
                    list.add(data);
                }
            }
        }
        if (JudgeNullUtil.iList(list)) {
            Set<Integer> delayTimes = new HashSet<>();
            Map<Integer, List<ControlModel>> delayData = new HashMap<>();
            List<ControlModel> configs;
            for (List<ControlModel> point : list) {
                for (ControlModel controlModel : point) {
                    delayTimes.add(controlModel.getDelayTime());// 所有延时时间
                    if (JudgeNullUtil.iList(delayData.get(controlModel.getDelayTime()))) {
                        configs = delayData.get(controlModel.getDelayTime());
                    } else {
                        configs = new ArrayList<ControlModel>();
                    }
                    configs.add(controlModel);
                    delayData.put(controlModel.getDelayTime(), configs);
                }
            }
            int intervalTime = 0;
            for (Integer delayTime : doSort(delayTimes)) {
                sendControllerCommond(delayTime - intervalTime, delayData.get(delayTime));// 按照延时时间分组发送
                intervalTime = delayTime;
            }
        }
        return result;
    }
    @Override
    public List<Trigger> selectTriggerByFaultCode() {
        // TODO Auto-generated method stub
        return tiggerDao.selectTriggerByFaultCode();
    }
    private List<Integer> doSort(Set<Integer> set) {
        final List<Integer> list = new ArrayList<Integer>();
        for (final Integer value : set) {
            list.add(value);
        }
        Collections.sort(list);
        return list;
    }
    public void sendControllerCommond(int delayTime, List<ControlModel> controlModelList) {
        try {
            Thread.sleep(delayTime * 1000L);
            EquipmentControlLog logs = RemoteControllerUtil.controller(controlModelList);// 发送控制指令到bolomi
            equipmentControlLogMongoDBDao.save(logs);// 保存发送命令
        } catch (InterruptedException e) {
            log.error("设备延迟启动异常,e:{}" + e);
        }
    }
}
